import { GpEcsWorld } from "../../GpEcsWorld";
import { Comp } from "../../CompDef";
import { Sglt } from "../../SgltDefine";
import { MathUtils, Rectangle, Vect3 } from "../../../../common/MathUtils";
import { GpEventDef } from "../../GpEventDef";
import { getDistance, makeDamage, makeBullet, makeLockBullet, makeRay, cure } from "./Utils";
import { CommonSystem } from "../CommonSystem";
import { MoveSystem } from "../MoveSystem";
import { HeroSystem } from "../HeroSystem";
import { GpCfg } from "../../GpCfgDef";
import { gg } from "../../../../../Game";
import ecs, { EcsComponent, EcsEntity, EcsEntityGroup, EcsWorld } from "ecs-ts";
export class BattleSystem extends ecs.EcsSystem<GpEcsWorld> {
    tempVec3 = new Vect3()
    uiInfo: Sglt.UiInfo
    worldInfo: Sglt.WorldInfo
    ownSkillsGroup: EcsEntityGroup = null



    constructor(world: GpEcsWorld, defaltGroupComps: (new () => EcsComponent)[] = [Comp.Transform, Comp.Battle.BattleInfo,Comp.Battle.Alive]) {
        super(world, defaltGroupComps);
        this.uiInfo = this.world.getSingleton(Sglt.UiInfo)
        this.worldInfo = this.world.getSingleton(Sglt.WorldInfo)
        this.ownSkillsGroup = this.world.getGroupByClz(Comp.Battle.OwnSkills)

    }

    getAttTarget(battleInfo: Comp.Battle.BattleInfo) {
        if (battleInfo.attTargetEntityId) {
            return this.world.getEntity(battleInfo.attTargetEntityId)
        }
        return null
    }


    onTriggerAttTimePoint(entity: EcsEntity, battleInfo: Comp.Battle.BattleInfo, target: EcsEntity, targetBattleInfo: Comp.Battle.BattleInfo) {
        if (battleInfo.lastAttTargetEntityId && battleInfo.lastAttTargetEntityId != target.id) {
            battleInfo.attSameTargetCount = 1
        } else {
            battleInfo.attSameTargetCount++
        }
        battleInfo.lastAttTargetEntityId = target.id

        battleInfo.curAttTriggered = true
        //如果是近战，直接结算伤害
        if (battleInfo.isMelee) {
            makeDamage(new DamageEventInfo(this.world, entity, battleInfo, target, targetBattleInfo))
        } else {//如果是远程，发射子弹
            makeLockBullet(this.world, entity, battleInfo, target, targetBattleInfo)
            // makeRay(this.world, entity, battleInfo, target, targetBattleInfo)
        }
        gg.eventTarget.emit(GpEventDef.onAttPointTriggered, entity, battleInfo, target, targetBattleInfo)
    }





    // tryAttTarget(entity: EcsEntity, battleInfo: Comp.Battle.BattleInfo, target: EcsEntity) {

    //     const targetBattleInfo = target.component(Comp.Battle.BattleInfo)

    //     if (battleInfo.attAnimPlaying) {
    //         const attFinisheTime = battleInfo.lastAttTimeMs + battleInfo.attInterval

    //         if (!battleInfo.curAttTriggered) {
    //             const attAnimTriggerTime = battleInfo.lastAttTimeMs + battleInfo.attInterval * battleInfo.attAnimTriggerTimeRatio

    //             if (this.world.elapsedTimeMs >= attAnimTriggerTime) {
    //                 this.onTriggerAttTimePoint(entity, battleInfo, target, targetBattleInfo)
    //             }
    //         }
    //         if (battleInfo.curAttTriggered && this.world.elapsedTimeMs > attFinisheTime) {
    //             battleInfo.attAnimPlaying = false
    //             battleInfo.curAttTriggered = false
    //             gg.eventTarget.emit(GpEventDef.onAttEnd, entity, battleInfo, target, targetBattleInfo)
    //         }
    //         return
    //     } else {
    //         /**如果攻击间隔没到，不攻击 */
    //         if (battleInfo.lastAttTimeMs + battleInfo.attInterval > this.world.elapsedTimeMs) {
    //             return
    //         }
    //         const targetTransform = target.component(Comp.Transform)
    //         const transform = entity.component(Comp.Transform)
    //         const direction = Vec3.subtract(this.tempVec3, targetTransform.pos, transform.pos)
    //         const angle = Vec3.angle(direction, transform.orientation)
    //         const attAngleDgree = battleInfo.attAngleDgree
    //         //如果角度>attAngleDgree度，不攻击
    //         if (angle > Math.PI / (180 / attAngleDgree)) {
    //             return
    //         }
    //         battleInfo.attAnimPlaying = true
    //         battleInfo.lastAttTimeMs = this.world.elapsedTimeMs

    //         gg.eventTarget.emit(GpEventDef.onAttStart, entity, battleInfo, target, targetBattleInfo)

    //     }

    // }




    //检查攻击逻辑
    // checkAttLogic() {
    //     this.defaultGroup.forEach((entity) => {
    //         const battleInfo = entity.component(Comp.Battle.BattleInfo)
    //         const transform = entity.component(Comp.Transform)
    //         // const rvo = entity.component(Comp.RVOMove)
    //         const move = entity.component(Comp.Move)

    //         const moveTargetDirectionMag = Vec3.mag(move.targetDirection)
    //         if (moveTargetDirectionMag > 0) {
    //             battleInfo.attTargetEntityId = 0
    //         }


    //         const attTarget = this.getAttTarget(battleInfo)
    //         let targetInRange = false

    //         if (attTarget) {
    //             const targetTransform = attTarget.component(Comp.Transform)

    //             const distance = this.getAttDistance(transform, targetTransform)
    //             if (distance <= battleInfo.attRange) {
    //                 this.tryAttTarget(entity, battleInfo, attTarget)
    //                 targetInRange = true

    //                 if (!move.hasForceMoveTargetPos) {
    //                     Vec3.set(move.targetPos, targetTransform.pos)
    //                     move.hasMoveTargetPos = false

    //                 }

    //             } else if (!move.hasMoveTargetPos) {
    //                 this.world.system(MoveSystem).tryMoveTo(entity, transform, move, targetTransform.pos)

    //             }
    //         } else {
    //             if (battleInfo.attTargetEntityId) {
    //                 battleInfo.attTargetEntityId = 0
    //                 move.hasMoveTargetPos = false
    //                 Vec3.set(move.targetPos, Vec3.ZERO)

    //             }
    //         }

    //     })
    // }


    tempRect: Rectangle = new Rectangle()
    tempQueryResult: EcsEntity[] = []

    findAttTarget(entity: EcsEntity, battleInfo: Comp.Battle.BattleInfo) {
        const force = entity.component(Comp.Force)
        let target = null
        let findEnemyRange = battleInfo.findEnemyRange
        this.tempQueryResult.length = 0
        const transform = entity.component(Comp.Transform)
        const quadTree = this.world.system(CommonSystem).quadTree
        MathUtils.getRectInDirection(transform.pos, { x: 0, y: 0, z: 0 }, findEnemyRange * 2, findEnemyRange * 2, this.tempRect)
        this.tempQueryResult = quadTree.query(this.tempRect, this.tempQueryResult)
        let lastDistance = 0

        this.tempQueryResult.forEach((queryItemEntity) => {
            const targetTransform = queryItemEntity.component(Comp.Transform)
            const targetPos = targetTransform.pos
            const targetDistance = getDistance(transform, targetTransform)
            if (queryItemEntity.id == entity.id || !queryItemEntity.component(Comp.Battle.BattleInfo) || queryItemEntity.component(Comp.Force).value == force.value) {
                return
            }
            if (!target) {
                target = queryItemEntity
                lastDistance = targetDistance
            } else if (targetDistance < lastDistance) {
                target = queryItemEntity
                lastDistance = targetDistance
            }
        })

        return target
    }

    //检查自动攻击目标
    checkAutoAttTarget() {
        const heroSystem = this.world.system(HeroSystem)
        this.defaultGroup.forEach((entity) => {
            const battleInfo = entity.component(Comp.Battle.BattleInfo)
            const action = entity.component(Comp.HeroAction)
            const force = entity.component(Comp.Force)
            if (action && battleInfo && battleInfo.enabelAutoAtt) {
                // TODO 临时代码，用来增加自动攻击动作
                if (!action.id) {
                    heroSystem.setAction(entity, action, force.value ? 4 : 1)
                }
            }
            // if (battleInfo.enabelAutoAtt && !battleInfo.attTargetEntityId && this.world.elapsedTimeMs - battleInfo.lastFindEnemyTimeMs >= battleInfo.findEnemyInterval) {
            //     const target = this.findAttTarget(entity, battleInfo)
            //     if (target) {
            //         battleInfo.attTargetEntityId = target.id
            //         battleInfo.findEnemyInterval = 0
            //     } else {
            //         battleInfo.findEnemyInterval = Math.min(battleInfo.findEnemyInterval + 100, battleInfo.maxFindEnemyInterval)
            //     }
            //     battleInfo.lastFindEnemyTimeMs = this.world.elapsedTimeMs

            // }

        })
    }


    checkAutoSkills() {
        const heroSystem = this.world.system(HeroSystem)
        this.ownSkillsGroup.forEach((entity) => {
            // if(entity.component(Comp.Transform).velocity.x>0||entity.component(Comp.Transform).velocity.y>0){
            //     return
            // }
            const ownSkills = entity.component(Comp.Battle.OwnSkills)
            if (ownSkills.skills.length == 0) { return }
            const action = entity.component(Comp.HeroAction)
            if (action && action.id) { return }
            const force = entity.component(Comp.Force)
            const skill = ownSkills.skills.find((i) => {
                const cfg = gg.cfgById(GpCfg.Skill, i.id)
                if (i.nextCanUseTimeMs <= this.world.elapsedTimeMs) {
                    return i
                }
            })
            if (action && skill) {
                // TODO 临时代码，用来增加自动释放技能
                const cfg = gg.cfgById(GpCfg.Skill, skill.id)

                heroSystem.setAction(entity, action, cfg.actionId, skill.id)

            }
        })
    }

    update(): void {
        this.checkAutoSkills()
        // this.checkAutoAttTarget()
        // this.checkAttLogic()


    }

}


export class DamageEventInfo {
    constructor(
        public world: EcsWorld,
        public entity: EcsEntity,
        public battleInfo: Comp.Battle.BattleInfo,
        public target: EcsEntity,
        public targetBattleInfo: Comp.Battle.BattleInfo,
        public value: number = 0,
        public isAoe = false
    ) { }
}
export class CureEventInfo {
    constructor(
        public world: EcsWorld,
        public entity: EcsEntity,
        public battleInfo: Comp.Battle.BattleInfo,
        public target: EcsEntity,
        public targetBattleInfo: Comp.Battle.BattleInfo,
        public isAoe = false
    ) { }
}
